<?php

namespace Kateba\UserBundle\Controller;

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Kateba\UserBundle\Entity\User;

class UserController extends Controller {

    /**
     * the main login action
     * @author Mahmoud
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function loginAction() {
        $request = $this->getRequest();
        $session = $request->getSession();
        if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
        } else {
            $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
            $session->remove(SecurityContext::AUTHENTICATION_ERROR);
        }
        return $this->render('KatebaUserBundle:User:login.html.twig', array(
                    'last_username' => $session->get(SecurityContext::LAST_USERNAME),
                    'error' => $error
        ));
    }

    /**
     * @author Mahmoud
     */
    public function redirectUserAction() {
        //get the session object
        $session = $this->getRequest()->getSession();
        //check if we have a url to redirect to
        $rediretUrl = $session->get('redirectUrl', FALSE);
        if (!$rediretUrl) {
            //check if firewall redirected the user
            $rediretUrl = $session->get('_security.secured_area.target_path');
            if (!$rediretUrl) {
                //redirect to home page
                $rediretUrl = $this->generateUrl('site_homepage');
            }
        } else {
            //remove the redirect url from the session
            $session->remove('redirectUrl');
        }
        return $this->redirect($rediretUrl);
    }

    /**
     * render the singup form in the base
     * @author Mahmoud
     */
    public function signupFormAction() {
        $user = new User();
        $formBuilder = $this->createFormBuilder($user, array(
                    'validation_groups' => array('signup')
                ))
                ->add('loginName')
                ->add('email')
                ->add('userPassword', 'repeated', array(
            'type' => 'password',
            'first_options' => array('attr' => array('autocomplete' => 'off')),
            'second_options' => array('attr' => array('autocomplete' => 'off')),
            'invalid_message' => "The passwords don't match"
        ));
        //create the form
        $form = $formBuilder->getForm();
        return $this->render('KatebaUserBundle:User:signupForm.html.twig', array(
                    'form' => $form->createView()
        ));
    }

    /**
     * the signup action
     * the link to this page should not be visible for the logged in user
     * @author Mahmoud
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function signUpAction() {
        //get the request object
        $request = $this->getRequest();
        //create an emtpy user object
        $user = new User();
        //create a signup form
        $formBuilder = $this->createFormBuilder($user, array(
                    'validation_groups' => array('signup')
                ))
                ->add('loginName')
                ->add('email')
                ->add('userPassword', 'repeated', array(
            'type' => 'password',
            'first_options' => array('attr' => array('autocomplete' => 'off')),
            'second_options' => array('attr' => array('autocomplete' => 'off')),
            'invalid_message' => "The passwords don't match"
        ));
        //create the form
        $form = $formBuilder->getForm();
        //check if this is the user posted his data
        if ($request->getMethod() == 'POST') {
            //fill the form data from the request
            $form->bindRequest($request);
            //check if the form values are correct
            if ($form->isValid()) {
                //get the entity manager
                $em = $this->getDoctrine()->getEntityManager();
                //prepare the body of the email
                $body = $this->renderView('KatebaUserBundle:User:Emails\welcome_to_site.txt.twig', array(
                    'user' => $user,
                    'password' => $user->getUserPassword()
                ));
                //get the role repo
                $roleRepository = $em->getRepository('KatebaUserBundle:Role');
                //get a user role object
                $role = $roleRepository->findOneByName('ROLE_NOTACTIVE');
                //get a update userName role object
                $roleUpdateUserName = $roleRepository->findOneByName('ROLE_UPDATABLE_USERNAME');
                //set user roles
                $user->addRole($role);
                $user->addRole($roleUpdateUserName);
                //store the object in the database
                $em->persist($user);
                $em->flush();
                //get the translator object
                $translator = $this->get('translator');
                //initialize a welcome message
                $welcomeMessage = $translator->trans('welcome') . ' ' . $user->__toString() . ' ' . $translator->trans('to our site');
                //prepare the message object
                $subject = $welcomeMessage;
                $message = $body;
                $headers = 'From: Educino <' . $this->container->getParameter('admin_notifications_email') . '>' . "\r\n";
                $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
                mail($user->getEmail(), $subject, $message, $headers);

//                $message = \Swift_Message::newInstance()
//                        ->setSubject($welcomeMessage)
//                        ->setFrom($this->container->getParameter('admin_notifications_email'))
//                        ->setTo($user->getEmail())
//                        ->setBody($body)
//                ;
//                //send the email
//                $this->get('mailer')->send($message);
                $session = $request->getSession();
                //try to login the user
                try {
                    // create the authentication token
                    $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
                    // give it to the security context
                    $this->get('security.context')->setToken($token);
                } catch (\Exception $e) {
                    //can not reload the user object log out the user
                    $this->get('security.context')->setToken(null);
                    //invalidate the current user session
                    $session->invalidate();
                }
                //set the success flag in the session
                $session->getFlashBag()->add('successSignup', true);
                return $this->redirect($this->generateUrl('site_homepage'));
            }
        }
        return $this->render('KatebaUserBundle:User:signup.html.twig', array(
                    'form' => $form->createView()
        ));
    }

    /**
     * this action will activate the user account and redirect him to the home page
     * after setting either success flag or error flag
     * @author Mahmoud
     * @param string $confirmationCode
     * @param string $email
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function activationAction($confirmationCode, $email) {
        //get the session object
        $session = $this->getRequest()->getSession();
        //get the entity manager
        $em = $this->getDoctrine()->getEntityManager();
        //check if the user is already active
        if (TRUE === $this->get('security.context')->isGranted('ROLE_USER')) {
            //set a notice flag
            $session->getFlashBag()->add('accountActive', true);
            return $this->redirect($this->generateUrl('site_homepage'));
        }
        //check if the user is already active
        if (TRUE === $this->get('security.context')->isGranted('ROLE_NOTACTIVE')) {
            //get the user object from the firewall
            $user = $this->get('security.context')->getToken()->getUser();
        } else {
            //get the user object from the database
            $user = $em->getRepository('KatebaUserBundle:User')->findOneBy(array('email' => $email, 'confirmationCode' => $confirmationCode));
        }
        if (!$user || $user->getConfirmationCode() != $confirmationCode || $user->getEmail() != $email) {
            //set an error flag
            $session->getFlashBag()->add('invalidConfirmationCode', true);
            //redirect to the login page
            return $this->redirect($this->generateUrl('site_homepage'));
        }
        //get a user role object
        $roleUser = $em->getRepository('KatebaUserBundle:Role')->findOneByName('ROLE_USER');
        //get the current user roles
        $userRoles = $user->getUserRoles();
        //try to get the not active role
        foreach ($userRoles as $key => $userRole) {
            //check if this role is the not active role
            if ($userRole->getName() == 'ROLE_NOTACTIVE') {
                //remove the not active role
                $userRoles->remove($key);
                //end the search
                break;
            }
        }
        //add the user role
        $user->addRole($roleUser);
        //save the new role for the user
        $em->flush();
        //try to refresh the user object roles in the firewall session
        try {
            // create the authentication token
            $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
            // give it to the security context
            $this->get('security.context')->setToken($token);
        } catch (\Exception $e) {
            //can not reload the user object log out the user
            $this->get('security.context')->setToken(null);
            //invalidate the current user session
            $session->invalidate();
        }
        //set a success flag
        $session->getFlashBag()->add('accountIsNowActive', true);
        //redirect to the login page
        return $this->redirect($this->generateUrl('site_homepage'));
    }

    /**
     * forgot your password action
     * this function gets the user email and sends him email to let him change his password
     * @author mahmoud
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function forgotPasswordAction() {
        //get the request object
        $request = $this->getRequest();
        //prepare the form validation constrains
        $collectionConstraint = new Collection(array(
            'email' => array(
                new Email(),
                new NotBlank()
            )
        ));
        //create the form
        $form = $this->createFormBuilder(null, array(
                    'validation_constraint' => $collectionConstraint,
                ))->add('email', 'email')
                ->getForm();
        //initialze the error string
        $error = FALSE;
        //check if form is posted
        if ($request->getMethod() == 'POST') {
            //bind the user data to the form
            $form->bindRequest($request);
            //check if form is valid
            if ($form->isValid()) {
                //get the form data
                $data = $form->getData();
                //get the email
                $email = $data['email'];
                //search for the user with the entered email
                $user = $this->getDoctrine()->getRepository('KatebaUserBundle:User')->findOneBy(array('email' => $email));
                //check if we found the user
                if ($user) {
                    //set a new token for the user
                    $user->setConfirmationCode(md5(uniqid(rand())));
                    //save the new user token into database
                    $this->getDoctrine()->getEntityManager()->flush();
                    //prepare the body of the email
                    $body = $this->renderView('KatebaUserBundle:User:Emails\forgot_your_password.txt.twig', array('user' => $user));
                    //prepare the message object
                    $subject = $this->get('translator')->trans('forgot your password');
                    $message = $body;
                    $headers = 'From: Educino <' . $this->container->getParameter('admin_notifications_email') . '>' . "\r\n";
                    $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
                    mail($user->getEmail(), $subject, $message, $headers);

//                    $message = \Swift_Message::newInstance()
//                            ->setSubject($this->get('translator')->trans('forgot your password'))
//                            ->setFrom($this->container->getParameter('admin_notifications_email'))
//                            ->setTo($user->getEmail())
//                            ->setBody($body)
//                    ;
//                    //send the email
//                    $this->get('mailer')->send($message);
                    //set the success message
                    $request->getSession()->getFlashBag()->add('emailSent', true);
                    return $this->redirect($this->generateUrl('site_homepage'));
                } else {
                    //set the error message
                    $error = true;
                }
            }
        }
        return $this->render('KatebaUserBundle:User:forgot_password.html.twig', array(
                    'form' => $form->createView(),
                    'error' => $error
        ));
    }

    /**
     * the change of password page
     * @author mahmoud
     * @param string $confirmationCode the token sent to the user email
     * @param string $email the user email
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function changePasswordAction($confirmationCode, $email) {
        //get the request object
        $request = $this->getRequest();
        //get the session object
        $session = $request->getSession();
        //get the entity manager
        $em = $this->getDoctrine()->getEntityManager();
        //try to get the user from the database
        $user = $em->getRepository('KatebaUserBundle:User')->findoneBy(array('email' => $email, 'confirmationCode' => $confirmationCode));
        //check if we found the user
        if (!$user) {
            //set an error flag
            $session->getFlashBag()->add('invalidConfirmationCode', true);
            //go to the login page
            return $this->redirect($this->generateUrl('site_homepage'));
        }
        //create a password form
        $form = $this->createFormBuilder($user, array(
                    'validation_groups' => array('password')
                ))
                ->add('userPassword', 'repeated', array(
                    'type' => 'password',
                    'first_name' => "Password",
                    'second_name' => "RePassword",
                    'invalid_message' => "The passwords don't match",
                ))
                ->getForm();
        //check if form is posted
        if ($request->getMethod() == 'POST') {
            //bind the user data to the form
            $form->bindRequest($request);
            //check if form is valid
            if ($form->isValid()) {
                //save the new hashed password
                $em->flush();
                //try to login the user
                try {
                    // create the authentication token
                    $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
                    // give it to the security context
                    $this->get('security.context')->setToken($token);
                } catch (\Exception $e) {
                    //can not reload the user object log out the user
                    $this->get('security.context')->setToken(null);
                    //invalidate the current user session
                    $session->invalidate();
                }
                //set the success flag
                $session->getFlashBag()->add('passwordChanged', true);
                //go to the edit profile page
                return $this->redirect($this->generateUrl('site_homepage'));
            }
        }
        return $this->render('KatebaUserBundle:User:change_password.html.twig', array(
                    'form' => $form->createView(),
                    'user' => $user
        ));
    }

    /**
     * the edit action
     * @author Mahmoud
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function editAction() {
        $request = $this->getRequest();
        $em = $this->getDoctrine()->getEntityManager();
        $user = $this->get('security.context')->getToken()->getUser();
        $message = false;
        $formValidationGroups = array('edit');
        //get the old user email
        $oldEmail = $user->getEmail();
        //create a password form
        $formBuilder = $this->createFormBuilder($user, array(
                    'validation_groups' => $formValidationGroups
                ))
                ->add('firstName')
                ->add('lastName')
                ->add('country', 'choice', array('required' => false, 'choices' => $user->getValidCountry()))
                ->add('email')
                ->add('city')
                ->add('state')
                ->add('highestEducationCompleted', 'choice', array('required' => false, 'choices' => $user->getValidHighestEducationCompleted()))
                ->add('currentGradeLevel', 'choice', array('required' => false, 'choices' => $user->getValidCurrentGradeLevel()))
                ->add('currentMajorConcentration', 'choice', array('required' => false, 'choices' => $user->getValidCurrentMajorConcentration()))
                ->add('GPA', 'choice', array('required' => false, 'choices' => $user->getValidGPA()))
                ->add('expectedEnrollmentSemester', 'choice', array('required' => false, 'expanded' => true, 'choices' => $user->getValidExpectedEnrollmentSemester()))
                ->add('expectedSemesterEnrollmentDate', 'choice', array('required' => false, 'choices' => $user->getValidExpectedSemesterEnrollmentYears()))
//                ->add('desiredCollegeUniversity')
                ->add('messageNotify', null, array('required' => false))
        ;
        //create the form
        $form = $formBuilder->getForm();
        //check if this is the user posted his data
        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            if ($form->isValid()) {
                $user = $form->getData();
                if ($request->get('desiredCollegeUniversityUndecided') != 'on') {
                    $user->setDesiredCollegeUniversity($request->get('hidden-tags'));
                } else {
                    $user->setDesiredCollegeUniversity('');
                }
                $user->setIntendedStudyField($request->get('hidden-intendedField'));
                //check if we need to change the user to not active
                if ($user->getEmail() != $oldEmail) {
                    //remove the role user
                    foreach ($user->getUserRoles() as $key => $roleObject) {
                        //check if this is the wanted role
                        if ($roleObject->getName() == 'ROLE_USER') {
                            //remove the role from the user
                            $user->getUserRoles()->remove($key);
                            //stop the search
                            break;
                        }
                    }
                    //get the not active role object
                    $role = $em->getRepository('KatebaUserBundle:Role')->findOneByName('ROLE_NOTACTIVE');
                    //check if the user already has the role
                    if (!$user->getUserRoles()->contains($role)) {
                        //add the role to the user
                        $user->addRole($role);
                    }
                    //prepare the body of the email
                    $body = $this->renderView('KatebaUserBundle:User:Emails\activate_email.txt.twig', array('user' => $user));
                    //prepare the message object
                    $subject = $this->get('translator')->trans('activate your account');
                    $message = $body;
                    $headers = 'From: Educino <' . $this->container->getParameter('admin_notifications_email') . '>' . "\r\n";
                    $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
                    mail($user->getEmail(), $subject, $message, $headers);

//                    $message = \Swift_Message::newInstance()
//                            ->setSubject($this->get('translator')->trans('activate your account'))
//                            ->setFrom($this->container->getParameter('admin_notifications_email'))
//                            ->setTo($user->getEmail())
//                            ->setBody($body)
//                    ;
//                    $this->get('mailer')->send($message);
                }
                $em->flush();
                $message = true;
            }
        }
        return $this->render('KatebaUserBundle:User:edit.html.twig', array(
                    'form' => $form->createView(),
                    'message' => $message,
                    'user' => $user
        ));
    }

    /**
     * the edit action
     * @author Mahmoud
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function changeMyPasswordAction() {
        $request = $this->getRequest();
        $user = $this->get('security.context')->getToken()->getUser();
        $message = false;
        $formValidationGroups = array('edit', 'oldPassword');
        //create a password form
        $formBuilder = $this->createFormBuilder($user, array(
                    'validation_groups' => $formValidationGroups
                ))
                ->add('userPassword', 'repeated', array(
                    'type' => 'password',
                    'first_name' => "Password",
                    'second_name' => "RePassword",
                    'invalid_message' => "The passwords don't match",
                    'required' => false
                ))
                ->add('oldPassword', 'password')
        ;
        //create the form
        $form = $formBuilder->getForm();
        //check if this is the user posted his data
        if ($request->getMethod() == 'POST') {
            $form->bindRequest($request);
            if ($form->isValid()) {
                $user->setValidPassword();
                $this->getDoctrine()->getEntityManager()->flush();
                $message = true;
            }
        }
        return $this->render('KatebaUserBundle:User:change_my_password.html.twig', array(
                    'form' => $form->createView(),
                    'message' => $message
        ));
    }

}
